package tau.facebook;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import tau.pimpmyfreedb.common.Network;
import tau.pimpmyfreedb.common.types.Gender;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

public class FacebookAPI
{
	private static final String APP_ID = "104904156316767";
	private static final String APP_SECRET = "0b6adcd5c0049828cfba1c0798e113cd";
	private static final String PERMISSIONS = "user_likes,friends_likes";

	private String token;	
	private ObjectMapper jsonMapper;	

	// constructors

	public FacebookAPI()
	{
		this.token = null;	
		this.jsonMapper = new ObjectMapper();		
	}

	public FacebookAPI(String token)
	{
		this();
		this.token = token;		
	}

	// setters
	
	public void setToken(String token) {
		this.token = token;
	}

	// getters

	public static String getLoginURL() {
		return "https://www.facebook.com/dialog/oauth?" + "client_id=" + APP_ID
				+ "&redirect_uri=https://www.facebook.com/connect/login_success.html" + "&response_type=token" + "&scope="
				+ PERMISSIONS;
	}

	public String getExtendTokenExpirationURL() {
		if (token == null)
			return null;

		return "https://graph.facebook.com/oauth/access_token?" + "client_id=" + APP_ID + "&client_secret=" + APP_SECRET
				+ "&grant_type=fb_exchange_token" + "&fb_exchange_token=" + token;
	}

	public String getUserName() {
		JsonNode me = getMe();
		if (me == null)
		  return null;
		
		return me.path("name").asText();
	}
	
	public String getToken() {
		return this.token;
	}

	public FacebookFriend[] getFriends() {

		// query the Facebook Graph
		String query = "SELECT uid, username, first_name, last_name, sex, pic, music " + "FROM user "
				+ "WHERE uid IN (SELECT uid2 FROM friend WHERE uid1 = me())";
		JsonNode friends = QueryTheGraph(query);
		friends = friends.path("data");

		// populate friends list
		List<FacebookFriend> friendsList = new LinkedList<FacebookFriend>();
		JsonNode cur;
		Long id;
		String username;
		String firstName;
		String lastName;
		String sex;
		Gender gender;
		String picUrl;
		String[] musicLikes;
		for (int i = 0; i < friends.size(); i++)
		{
			cur = friends.path(i);

			// get values from current JsonNode
			id = cur.path("uid").asLong(0);
			username = cur.path("username").textValue();
			firstName = cur.path("first_name").textValue();
			lastName = cur.path("last_name").textValue();
			sex = cur.path("sex").textValue();
			gender = (sex == "male" ? Gender.Male : sex == "female" ? Gender.Female : Gender.Unknown);
			picUrl = cur.path("pic").textValue();
			musicLikes = cur.path("music").textValue().split(",");
			for (int j = 0; j < musicLikes.length; j++)
				musicLikes[j] = musicLikes[j].trim();

			// add a new FacebookFriend to the list
			friendsList.add(new FacebookFriend(id, username, firstName, lastName, gender, picUrl, musicLikes));
		}

		FacebookFriend[] friendsArr = new FacebookFriend[friendsList.size()];
		return friendsList.toArray(friendsArr);
	}

	public String getUserPermissions() {
		try
		{
			// get the permissions
			String url = "https://graph.facebook.com/me/permissions?access_token=" + token;
			JsonNode node = jsonMapper.readTree(Network.SendHttpGetRequest(url));

			// create string representation
			String str = "";
			node = node.path("data").path(0);
			for (Iterator<String> it = node.fieldNames(); it.hasNext();)
				str += "\t" + it.next() + "\n";

			// return
			return str;
		} catch (Exception ex)
		{
			return null;
		}
	}

	// misc

	public String Logout() {
		try
		{
			String url = "https://www.facebook.com/logout.php?" + "next=smooth-mountain-4928.herokuapp.com" + "&access_token=" + token;
			return Network.SendHttpGetRequest(url);
		} catch (Exception ex)
		{
			return null;
		}
	}
	
	private JsonNode getMe() {
	  try
    {
      String url = "https://graph.facebook.com/me&access_token=" + token;
      String response = Network.SendHttpGetRequest(url);
      return jsonMapper.readTree(response);
    } catch (Exception e)
    {
      e.printStackTrace();
    }

    return null;
	}
	
	private JsonNode QueryTheGraph(String query) {

		try
		{
			String url = "https://graph.facebook.com/fql?q=" + query.replace(" ", "+") + "&access_token=" + token;
			String response = Network.SendHttpGetRequest(url);
			return jsonMapper.readTree(response);
		} catch (Exception e)
		{
			e.printStackTrace();
		}

		return null;
	}
}
